DEFINITION MODULE Kernel;

(* (C) Copyright 1987 Fitted Software Tools. All rights reserved.

    This module is part of the example multitasking communications program
    provided with the Fitted Software Tools' Modula-2 development system.

    Registered users may use this program as is, or they may modify it to
    suit their needs or as an exercise.

    If you develop interesting derivatives of this program and would like
    to share it with others, we encourage you to upload a copy to our BBS.
*)

(*
    This is the multitasking kernel.

    The terms process and task are used interchangeably throughout...

    The kernel contains a scheduler that dispatches the CPU to the next
    available "ready to run" task whenever some task makes a request that
    prevents it from continuing running.

    Tasks may be suspended for one of three reasons:
        1-  when issuing a WaitIO, until the interrupt occurs.
        2-  when issuing a Lock on a LockHeader already locked by another
            task.
        3-  when issuing a Wait, if no signals are pending on that
            particular SignalHeader.

    Resuming tasks:
        1-  If a task is waiting on an IO and the interrupt occurs, this
            task preempts the currently executing one.
        2-  If a task is suspended on a LockHeaderm it is made "ready to
            run" when the LockHeader is unlocked.
        3-  If a task is suspended on a SignalHeader, it is made "ready
            to run" when a Signal is sent to this SignalHeader.

    A task that is in a "ready to run" state, is resumed when the tasks
    ahead of it in the ready list get removed (suspended).

    The kernel provides an idle process that runs whenever nothing else
    can. This idle process simply loops.
*)

FROM SYSTEM IMPORT ADDRESS;

TYPE
    SignalHeader;
    LockHeader;

PROCEDURE NewProcess( p :PROC; n :CARDINAL; iop :BOOLEAN );
(*
    Creates a new process structure and places it in the ready list.
    The process is not started.

    p is the main procedure for the process.

    n is the size of the stack to allocate for the process.

    iop should be TRUE if this is an I/O process -- I/O processes are
    higher priority than the other processes.
*)

PROCEDURE InitSignal( VAR s :SignalHeader );
(*
    Initialize the signal header.
    Must be invoked before a Signal or Wait is done on this header.
*)

PROCEDURE Signal( VAR s :SignalHeader );
(*
    Send a signal to the signal header.
    If a process is Waiting on theis header, it is made "ready",
    otherwise the signal count is incremented.
*)

PROCEDURE Wait( VAR s :SignalHeader );
(*
    If the signal count in this signal header is not 0, it is decremented
    and the process continues; otherwise, the process is suspended.
*)

PROCEDURE InitLock( VAR l :LockHeader );
(*
    Initialize the lock header.
    Must be invoked before a Lock or Unlock is done on this header.
*)

PROCEDURE Lock( VAR l :LockHeader );
(*
    If this header is free (or already locked by the current process)
    give the lock to this process. In this case, the process continues
    running.

    If this header is locked by another process, suspend.
*)

PROCEDURE Unlock( VAR l :LockHeader );
(*
    If the calling process owns this lock header, the lock is freed up;
    If there was a process suspended on this lock header, that process
    is made "ready" and given the lock.
*)

PROCEDURE WaitIO( v :CARDINAL );
(*
    Suspend the current process until an interrupt occurs on vector v.
*)

END Kernel.